import React, { useState, ReactElement, useEffect } from 'react'
import style from './LoginForm.module.less'
import Phone from './Phone'
import SMSInput from './SMSInput'
import Agree from './Agree'
import Username from './Username'
import Password from './Password'
import { State } from '../reducer'
import classNames from 'classnames'
import { awaitWrap } from '@js/tool'
import { getCaseListRequest, loginByMobileRequest, loginByUsernameRequest } from '../ajax'
import { message } from 'antd'
import { connect } from 'react-redux'
import { setToken, setUserInfo, USERINFO } from '@redux/actions/basic'
import { History } from 'history'

interface Props {
  state: State
  dispatch: (o: any) => void
  setToken: typeof setToken
  setUserInfo: typeof setUserInfo
  history: History
}

interface BlockProps {
  state: State
  dispatch: (o: any) => void
  onEnter: () => void
}

function LoginByMobile ({ state, dispatch, onEnter }: BlockProps): ReactElement {
  return (
    <>
      <Phone zoneNum={state.zoneNum} mobile={state.mobile} dispatch={dispatch} onEnter={onEnter} />
      <div className={style['notice-line']}>{state.mobileError}</div>
      <SMSInput mobile={state.mobile} validateCode={state.validateCode} dispatch={dispatch} onEnter={onEnter}/>
      <div className={style['notice-line']}>{state.validateCodeError}</div>
    </>
  )
}

function LoginByUsername ({ state, dispatch, onEnter }: BlockProps): ReactElement {
  return (
    <>
      <Username value={state.username} dispatch={dispatch} onEnter={onEnter} />
      <div className={style['notice-line']}>{state.usernameError}</div>
      <Password value={state.password} dispatch={dispatch} onEnter={onEnter} />
      <div className={style['notice-line']}>{state.passwordError}</div>
    </>
  )
}

// 重置错误提示
function resetNotice (dispatch: (v: any) => void): void {
  dispatch({ type: 'mobileError', data: '' })
  dispatch({ type: 'validateCodeError', data: '' })
  dispatch({ type: 'usernameError', data: '' })
  dispatch({ type: 'passwordError', data: '' })
}

// 验证提交数据
function validate (isLoginByMobile: boolean, state: State, dispatch: (v: any) => void): boolean {
  resetNotice(dispatch)
  const { zoneNum, mobile, validateCode } = state
  if (isLoginByMobile) {
    if (!/^\d{2,4}$/.test(zoneNum)) {
      dispatch({ type: 'mobileError', data: '区号格式不正确' })
      return false
    } else if (!/^1\d{10}$/.test(mobile)) {
      dispatch({ type: 'mobileError', data: '手机号格式不正确' })
      return false
    } else if (!/^\d{4}$/.test(validateCode)) {
      dispatch({ type: 'validateCodeError', data: '验证码格式不正确' })
      return false
    }
  }
  return true
}

// 验证是否可以提交
function validateSubmitable (isLoginByMobile: boolean, state: State, dispatch: (v: any) => void): boolean {
  const { zoneNum, mobile, validateCode, username, password, agree } = state
  if (isLoginByMobile) {
    return zoneNum.length !== 0 && mobile.length === 11 && validateCode.length === 4 && agree
  }
  return username.length !== 0 && password.length !== 0 && agree
}

// 登录按钮点击回调
async function submitHandle (isLoginByMobile: boolean, state: State, dispatch: (v: any) => void, setToken: (v: string) => void, setUserInfo: (v: USERINFO) => void, history: History): Promise<void> {
  if (state.login || !validateSubmitable(isLoginByMobile, state, dispatch) || !validate(isLoginByMobile, state, dispatch)) {
    return undefined
  }
  dispatch({ type: 'login', data: true })
  const fn = isLoginByMobile ? loginByMobileRequest.bind(null, state.zoneNum, state.mobile, state.validateCode) : loginByUsernameRequest.bind(null, state.username, state.password)
  const hide = message.loading('登录中', 120)
  const [e, d] = await awaitWrap(fn())
  dispatch({ type: 'login', data: false })
  hide()
  if (e !== null) {
    return undefined
  } else if (d !== null) {
    setToken(d.token)
    setUserInfo(d.userInfo)
    await message.success('登录成功', 1)
    if (d.userInfo.is_auth === 0) {
      history.push('/verification')
    } else {
      await getCaseList(history)
    }
  }
}

// 获取案件列表并决定跳转地址
async function getCaseList (history: History): Promise<void> {
  const hide = message.loading('加载中', 120)
  const [e, d] = await awaitWrap(getCaseListRequest())
  hide()
  if (e !== null) {
    history.push('/admin/case-list')
    return undefined
  }
  if (d === null || d !== 0) {
    history.push('/admin/case-list')
  } else {
    history.push('/admin/new-case')
  }
}

function Main ({ state, dispatch, setToken, setUserInfo, history }: Props): ReactElement {
  const [isLoginByMobile, setIsLoginByMobile] = useState(true)
  const [submitable, setSubmitable] = useState(false)
  const submitName = classNames(style.submit, { [style.active]: submitable })
  useEffect(() => {
    setSubmitable(validateSubmitable(isLoginByMobile, state, dispatch))
  }, [isLoginByMobile, state.mobile, state.validateCode, state.username, state.password, state.agree])
  const loginFn: () => void = async () => await submitHandle(isLoginByMobile, state, dispatch, setToken, setUserInfo, history)
  return (
    <div className={style.container}>
      <div className={style['title-line']}>当事人登录</div>
      <div className={style['sub-title-line']}>
        注册手机号和名字应该保持一致
      </div>
      <div className={style['notice-line']}></div>
      {isLoginByMobile
        ? <LoginByMobile state={state} dispatch={dispatch} onEnter={loginFn} />
        : <LoginByUsername state={state} dispatch={dispatch} onEnter={loginFn} />}
      <div className={style['toggle-btn']} onClick={() => setIsLoginByMobile(!isLoginByMobile)}>
        {isLoginByMobile ? '账号密码登录' : '手机验证码登录'}
      </div>
      <Agree value={state.agree} dispatch={dispatch} />
      <button className={submitName} onClick={loginFn}>登录</button>
    </div>
  )
}

export default connect((state) => {
  return {}
}, (dispatch) => {
  return {
    setToken: (i: string) => dispatch(setToken(i)),
    setUserInfo: (i: USERINFO) => dispatch(setUserInfo(i))
  }
})(Main)
